package com.tsd.core.exception;

import com.tsd.core.utils.ExceptionUtil;
import com.tsd.core.utils.ResponseUtil;
import com.tsd.core.vo.ErrorCode;
import com.tsd.core.vo.HttpResult;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Set;

/**
 * @ClassName: GlobalExceptionHandler
 * @Description: TODO
 * @Author: admin
 * @Date: 2022/11/15 10:59
 * @Version: 1.0
 */
@ControllerAdvice
@Order
public class GlobalExceptionHandler {

    public static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public Object badArgumentHandler(IllegalArgumentException e) {
        LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        return ResponseUtil.badArgument(e.getMessage());
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseBody
    public Object badArgumentHandler(MethodArgumentTypeMismatchException e) {
        LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        return ResponseUtil.badArgument(e.getMessage());
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public Object badArgumentHandler(MissingServletRequestParameterException e) {
        LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        return ResponseUtil.badArgument(e.getMessage());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseBody
    public Object badArgumentHandler(HttpMessageNotReadableException e) {
        LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        return ResponseUtil.badArgument(e.getMessage());
    }

    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public Object badArgumentHandler(ValidationException e) {
        LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        if (e instanceof ConstraintViolationException) {
            ConstraintViolationException exs = (ConstraintViolationException) e;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
                String message = ((PathImpl) item.getPropertyPath()).getLeafNode().getName() + item.getMessage();
                return ResponseUtil.fail(402, message);
            }
        }
        return ResponseUtil.badArgument(e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Object seriousHandler(Exception e) {
        LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        return HttpResult.fail(ErrorCode.CODE_PROC_ERROR, e.getMessage());
    }

    @ExceptionHandler(GlobalException.class)
    @ResponseBody
    public HttpResult<Object> globalExceptionHandler(GlobalException e) {
        LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        return HttpResult.fail(e.getCode(), e.getMessage());
    }
}
